
import { Point, TMat2D } from "fabric";

export const iMatrix = Object.freeze([1, 0, 0, 1, 0, 0]);

// export const applyTransformToObject = (
//     object,
//     transform,
// ) => {
//     const { translateX, translateY, scaleX, scaleY, ...otherOptions } =
//         qrDecompose(transform),
//         center = new Point(translateX, translateY);
//     object.flipX = false;
//     object.flipY = false;
//     Object.assign(object, otherOptions);
//     object.set({ scaleX, scaleY });
//     object.setPositionByOrigin(center, CENTER, CENTER);
// };

export const invertTransform = (t) => {
    const a = 1 / (t[0] * t[3] - t[1] * t[2]),
        r: TMat2D = [a * t[3], -a * t[1], -a * t[2], a * t[0], 0, 0],
        { x, y } = new Point(t[4], t[5]).transform(r, true);
    r[4] = -x;
    r[5] = -y;
    return r;
};

export const multiplyTransformMatrices = (
    a,
    b,
    is2x2?: boolean,
) =>
    [
        a[0] * b[0] + a[2] * b[1],
        a[1] * b[0] + a[3] * b[1],
        a[0] * b[2] + a[2] * b[3],
        a[1] * b[2] + a[3] * b[3],
        is2x2 ? 0 : a[0] * b[4] + a[2] * b[5] + a[4],
        is2x2 ? 0 : a[1] * b[4] + a[3] * b[5] + a[5],
    ];

/**
 * We are actually looking for the transformation from the destination plane to the source plane (change of basis matrix)\
 * The object will exist on the destination plane and we want it to seem unchanged by it so we invert the destination matrix (`to`) and then apply the source matrix (`from`)
 * @param [from]
 * @param [to]
 * @returns
 */
export const calcPlaneChangeMatrix = (from = iMatrix, to = iMatrix) => multiplyTransformMatrices(invertTransform(to), from);
/**
 * Sends a point from the source coordinate plane to the destination coordinate plane.\
 * From the canvas/viewer's perspective the point remains unchanged.
 *
 * @example <caption>Send point from canvas plane to group plane</caption>
 * var obj = new Rect({ left: 20, top: 20, width: 60, height: 60, strokeWidth: 0 });
 * var group = new Group([obj], { strokeWidth: 0 });
 * var sentPoint1 = sendPointToPlane(new Point(50, 50), undefined, group.calcTransformMatrix());
 * var sentPoint2 = sendPointToPlane(new Point(50, 50), iMatrix, group.calcTransformMatrix());
 * console.log(sentPoint1, sentPoint2) //  both points print (0,0) which is the center of group
 *
 * @param {Point} point
 * @param {TMat2D} [from] plane matrix containing object. Passing `undefined` is equivalent to passing the identity matrix, which means `point` exists in the canvas coordinate plane.
 * @param {TMat2D} [to] destination plane matrix to contain object. Passing `undefined` means `point` should be sent to the canvas coordinate plane.
 * @returns {Point} transformed point
 */
export const sendPointToPlane = (point, from = iMatrix, to = iMatrix) => point.transform(calcPlaneChangeMatrix(from, to));
/**
 * See {@link sendPointToPlane}
 */
export const sendVectorToPlane = (point, from = iMatrix, to = iMatrix) => point.transform(calcPlaneChangeMatrix(from, to), true);

// export const sendObjectToPlane = (object, from, to) => {
//     const t = calcPlaneChangeMatrix(from, to);
//     applyTransformToObject(object, multiplyTransformMatrices(t, object.calcOwnMatrix()));
//     return t;
// };
